// SharksView.cpp : implementation of the CSharksView class
//

// by GMKal
// last modified:  4/11/2005   20:31

#include "stdafx.h"
#include "Sharks.h"

#include "SharksDoc.h"
#include "SharksView.h"
#include ".\sharksview.h"
#include "SharkSettingsDlg.h"
#include "ParamHandler.h"
#include "Preprocessor.h"
#include "text.h"

#include <process.h>
#include <stdio.h>

#pragma warning(disable : 4996)

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define YANGLE_SPEED 1.0f
#define XANGLE_SPEED 1.0f
#define ZOOM_SPEED 0.2f
#define INITIAL_CAMERA_HEIGHT 5.0f

#define FOV_NORMAL	60.0
#define FOV_SHARKEYE 160.0

#define DEFAULT_SCRIPT "default.fish"

GLText gltext;

//Vector3 vcampos,vcamview;
//Vector3 vbezcampos,vbezcamview;

// CSharksView

IMPLEMENT_DYNCREATE(CSharksView, COpenGLView)

BEGIN_MESSAGE_MAP(CSharksView, COpenGLView)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_KEYDOWN()
	ON_WM_RBUTTONDOWN()
	ON_COMMAND(ID_SETTINGS_PROGRAMOPTIONS, OnSettingsProgramOptions)
	ON_COMMAND(ID_NAVIGATION_GOTONEXTSHARK, OnNavigationGotonextshark)
	ON_COMMAND(ID_NAVIGATION_GOTOPREVIOUSSHARK, OnNavigationGotopreviousshark)
	ON_WM_SETFOCUS()
	ON_WM_KILLFOCUS()
	ON_COMMAND(ID_NAVIGATION_GOTOCENTEROFTERRAIN, OnNavigationGotocenterofterrain)
	ON_COMMAND(ID_NAVIGATION_FOLLOWPREVIOUSSHARK, OnNavigationFollowpreviousshark)
	ON_COMMAND(ID_NAVIGATION_FOLLOWNEXTSHARK, OnNavigationFollownextshark)
	ON_WM_SIZE()
	ON_COMMAND(ID_EDIT_SCRIPTEDITOR, OnEditScripteditor)
	ON_COMMAND(ID_FILE_OPENSCRIPT, OnFileOpenscript)
	ON_COMMAND(ID_EDITOR_NEWSCRIPT, OnEditorNewscript)
	ON_COMMAND(ID_EDIT_RELOADSCRIPT, OnEditReloadscript)
END_MESSAGE_MAP()

// CSharksView construction/destruction


// TODO: all those values should be read from an .ini file
CSharksView::CSharksView()
{
	m_bShowBoundingSpheres=FALSE;
	m_bShowCaustics=TRUE;
	m_bEnableCulling=FALSE;
	m_bShowWireframe=FALSE;
	m_bShowSharkShadows=TRUE;
	m_bShowPaths=FALSE;
	m_bPaused=TRUE;
	m_bHasFocus=TRUE;
	m_bShowCredits=FALSE;
	m_bShowHelp=TRUE;
	

	m_fovy = FOV_NORMAL;

	m_iCameraFish=-1;		// currently looking to no shark
	m_bCameraFollowsFish=FALSE;

	m_iCursorShow=1;		// initially the cursor is displayed
	m_pFishManager = NULL;
	pfont=NULL;
	
	m_terrainSize=100.f;
	m_terrainTile=10;
	m_caustiScale=.3f;
	m_curCaustic=0;
	m_causticTimeElapsed=0;
	m_changeCaustInterv=0.05;	// 20 changes every second
	
	m_cameraMode = WAYPOINT_CAMERA;
	m_waypointCamZoom=2.f;
	//m_strCameraMode = "Waypoint Camera Mode \n(use arrows to follow next shark)";
	//mStrMainScriptFile = "default.fish";

	
	m_lightpos[0]=0;	m_lightpos[1]=20;	m_lightpos[2]=0; 
	m_matamb[0]=0.;		m_matamb[1]=0.f;	m_matamb[2]=0.f;
	m_matdiff[0]=0.0f;	m_matdiff[1]=1.0f;	m_matdiff[2]=1.0f;
	m_matspec[0]=.0f;	m_matspec[1]=.6f;	m_matspec[2]=0.6f;	m_matspec[3]=1.f;
	m_clrColor[0]=.0f;	m_clrColor[1]=.302f; m_clrColor[2]=.745f; m_clrColor[3]=1.0f;
	
	memcpy(m_sharkShadowColor,m_clrColor,sizeof(float)*4);
	
	m_planeHeight=-2;
	m_windowTitle="Sharks Demo 2009 v0.1a ";

	m_box.SetCenter(0,1,0);
	m_ray.SetOrigin(5,2,0);
	m_ray.SetDirection(-100,2,0);
	m_sphere.SetCenter(-1,2,0);
	m_sphere.SetRadius(0.2f);
}

CSharksView::~CSharksView()
{
}

BOOL CSharksView::PreCreateWindow(CREATESTRUCT& cs)
{
	return COpenGLView::PreCreateWindow(cs);
}

// CSharksView drawing

void CSharksView::OnDraw(CDC* pDC)
{
	CSharksDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	COpenGLView::OnDraw(pDC);
}


// CSharksView diagnostics

#ifdef _DEBUG
void CSharksView::AssertValid() const
{
	COpenGLView::AssertValid();
}

void CSharksView::Dump(CDumpContext& dc) const
{
	COpenGLView::Dump(dc);
}

CSharksDoc* CSharksView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CSharksDoc)));
	return (CSharksDoc*)m_pDocument;
}
#endif //_DEBUG


// CSharksView message handlers



/*
 *	all drawing goes here
 */
void CSharksView::RenderScene()
{
	glLoadIdentity();
	
	double dt = m_timer.Tick();

	if(m_cameraMode==FIRSTPERSON_CAMERA)
	{
		//ShowCursor(FALSE);
		m_pcamera->Update(this,dt);
		m_pcamera->Apply();
	}
	else if(m_cameraMode==WAYPOINT_CAMERA)
	{
		//ShowCursor(TRUE);
		if(m_bCameraFollowsFish && m_pwaypointCam->Update(dt))
		{
			ASSERT(m_pCameraFish);
			m_bPaused=m_bWasPaused;	// restore pause state
			m_pwaypointCam->SetPosition(m_pCameraFish->GetPosition()+
				Vector3(0,m_waypointCamZoom,1.3f*m_waypointCamZoom));
			m_pwaypointCam->SetView(m_pCameraFish->GetPosition());
		}
		else
		{
			m_pwaypointCam->Update(dt);			
		}
		m_pwaypointCam->Apply();
	}
	else if(m_cameraMode==SHARKEYE_CAMERA)	
	{
		ASSERT(m_pCameraFish);
		//ShowCursor(TRUE);
		Vector3 p(m_pCameraFish->GetPosition());
		Vector3 target(0,0,2.0f);
		Quaternion q(m_pCameraFish->GetRotation());
		q.RotateVector(target,false);
		Vector3 c(p+target);
		Vector3 v(p+2*target);
		gluLookAt(c.x,c.y,c.z,v.x,v.y,v.z,0,1,0);		
	}

	//
	// update the frustum (must be *after* any camera application)
	m_pfrustum->Update();

	//
	// if using multi-texture, change caustic if its time
	if(GLEW_ARB_multitexture && m_bShowCaustics)
	{
		glActiveTextureARB(GL_TEXTURE1_ARB);	// in unit1 we keep the caustics
		glEnable(GL_TEXTURE_2D);				// enable texturing for second unit
		
		if(!m_bPaused)
		{
			m_causticTimeElapsed += dt;
			if(m_causticTimeElapsed>m_changeCaustInterv)
			{
				m_curCaustic = (m_curCaustic<31)? (m_curCaustic+1) : 0;
				m_causticTimeElapsed=0;	// reset time
				glBindTexture(GL_TEXTURE_2D,caustTexures[m_curCaustic]);
			}
		}
	}


	

	//
	// animate sharks and draw them
	if(!m_bPaused) 
		m_pFishManager->Update(dt);
	m_pFishManager->DrawSharks();
	
	//
	// render the ground
	RenderGround();

	//
	// disable multitexturing while drawing text
	if(GLEW_ARB_multitexture && m_bShowCaustics)
	{
		glActiveTextureARB(GL_TEXTURE1_ARB);
		glDisable(GL_TEXTURE_2D);
		glActiveTextureARB(GL_TEXTURE0_ARB);		
	}
	
	//TestRay();	// simple ray tracing test

	// show first fish info (just a message for now)
	ShowFishInfo(0);
	
	//
	// show credits
	if(m_bShowCredits)
		ShowCredits();

	//
	// show help
	if (m_bShowHelp)
		ShowCameraHelp();

	//
	// show fps in window title
	CalcAndSetFPS(dt);

	//
	// start immediately drawing the next frame if the view has the focus
	if(m_bHasFocus)
		Invalidate(FALSE);	
}

/*
 *	
 */
void CSharksView::RenderBackgroundQuad()
{
//	glPushAttrib(GL_ENABLE_BIT);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	glPushMatrix();
	glLoadIdentity();
	//glShadeModel(GL_SMOOTH);
	glBegin(GL_QUADS);
	{
		//
		// background
		/*glColor3ub(0,0,10);
		glVertex3f(-10,-10,-25);
		glVertex3f( 10,-10,-25);
		glColor3ub(5,157,252);
		glVertex3f( 10,10,-25);
		glVertex3f(-10,10,-25);		*/

		//
		// floor
		glColor3ub(20,200,255);
		glVertex3f(-10,-1 ,-1);
		glVertex3f( 10,-1 ,-1);
		glColor3ub(0,0,0);
		glVertex3f( 10,-1, -10);
		glVertex3f(-10,-1, -10);		

	}
    glEnd();
	glPopMatrix();
	glEnable(GL_LIGHTING);
	glEnable(GL_TEXTURE_2D);
//	glPopAttrib();
}


/*
 *	all init goes here
 */
int CSharksView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (COpenGLView::OnCreate(lpCreateStruct) == -1)
		return -1;

	ResetLogFile();
	glewInit();		
	TextureManager::pinstance();	// force DevIL to init

	//pfont = new GLFont();
	gltext.Load("data/font.tga");

	//
	// create the frustum
	m_pfrustum = new Frustum;

	//
	// init shark manager
	m_pFishManager = new FishManager;
	//m_pFishManager->Init();
	m_pFishManager->mpbShowSharkShadows = &m_bShowSharkShadows;
	m_pFishManager->mpLightPos = m_lightpos;
	m_pFishManager->mpPlaneHeight = &m_planeHeight;
	m_pFishManager->mpFrustum = m_pfrustum;
	m_pFishManager->mSharkShadowColor = m_sharkShadowColor;
	m_pFishManager->mpbShowBoundingSpheres = &m_bShowBoundingSpheres;
	m_pFishManager->mpbEnableCulling = &m_bEnableCulling;
	m_pFishManager->mpbMultitexture = &m_bShowCaustics;
	m_pFishManager->mpbShowPaths = &m_bShowPaths;
	m_pFishManager->mpbShowWireframe = &m_bShowWireframe;
	
	



	//
	// create cameras before reading .ini file
	m_pcamera = new Camera;
	m_pcamera->SetPosition(0,1,5);
	m_pcamera->SetView(0,0,0);
	m_pwaypointCam = new BezierCamera;
	m_pwaypointCam->SetPosition(0,3,6);
	m_pwaypointCam->SetView(0,0,0);

	ReadIniFile();	
	LoadMainScript("./scripts/main.fish");



	m_pFishManager->mWorldBounds.m_center = Vector3(0, 3 ,0);
	m_pFishManager->mWorldBounds.m_xdim = m_terrainSize*0.45f;
	m_pFishManager->mWorldBounds.m_ydim = 3.f;
	m_pFishManager->mWorldBounds.m_zdim = m_terrainSize*0.45f;


	//
	// init timer
	m_timer.Reset();

	//
	// init cameras, first the first person camera...
	//m_pcamera->SetPosition(0,1,5);
	//m_pcamera->SetView(0,0,0);
	m_pcamera->Update(this,0.0);

	//
	// ... then the way point camera
	//m_pwaypointCam->SetPosition(0,3,6);
	//m_pwaypointCam->SetView(0,0,0);
	m_pwaypointCam->Update(0.0);

	//
	// if we are in first-person view, hide the cursor
	if(m_cameraMode==FIRSTPERSON_CAMERA)
		ShowCursor(FALSE);

	
	
	//
	// load any texture (expect the ones for the shark models, that will be taken
	// care of by the shark manager
	LoadTextures();

	SetClearColor(m_clrColor);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_DEPTH_TEST);
	glClearDepth(1.0f);				
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);

	glLightfv(GL_LIGHT0,GL_AMBIENT,m_matamb);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,m_matdiff);
	glLightfv(GL_LIGHT0,GL_SPECULAR,m_matspec);
	glLightfv(GL_LIGHT0,GL_POSITION,m_lightpos);
	glEnable(GL_LIGHT0);

	glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);

	glEnable(GL_CULL_FACE);
	glEnable(GL_LIGHTING);
	glEnable(GL_COLOR_MATERIAL);
	glColorMaterial(GL_FRONT,GL_AMBIENT_AND_DIFFUSE);



	//
	// if multi-texturing is supported, set parameters for the 2nd texture unit
	if(GLEW_ARB_multitexture && m_bShowCaustics)
	{
		glActiveTextureARB(GL_TEXTURE1_ARB);

		GLfloat sPlane[4] = { m_caustiScale, 0.3f, 0.0f, .0f };
		GLfloat tPlane[4] = { 0.0f, 0.3f, m_caustiScale, .0f };
		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
		glTexGenfv(GL_S, GL_OBJECT_PLANE, sPlane);
		glTexGenfv(GL_T, GL_OBJECT_PLANE, tPlane);
		glEnable(GL_TEXTURE_GEN_S);
		glEnable(GL_TEXTURE_GEN_T);

		glBindTexture(GL_TEXTURE_2D,caustTexures[m_curCaustic]);
		/*glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
		glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);*/

		glActiveTextureARB(GL_TEXTURE0_ARB);
		//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
		//glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD);
	}

	//
	// enable fog
	glEnable(GL_FOG);
	{
		//GLfloat fogColor[4] = {0.0f, 0.0f, 0.5f, 1.0f};
		GLfloat fogColor[4];
		memcpy(fogColor,m_clrColor,sizeof(GLfloat)*4);	// set the fog color same 
														// as the clear color
		GLenum fogMode = GL_EXP;
		glFogi(GL_FOG_MODE, fogMode);
		glFogfv(GL_FOG_COLOR, fogColor);
		glFogf(GL_FOG_DENSITY, 0.05f);
		glHint(GL_FOG_HINT, GL_DONT_CARE);
		glFogf(GL_FOG_START, 2.0f);
		glFogf(GL_FOG_END, 30.0f);
	}	


	

	return 0;
}



/*
 *	clean up here
 */
void CSharksView::OnDestroy()
{
	COpenGLView::OnDestroy();

	delete m_pFishManager;
	m_pFishManager=NULL;

	//
	// fonts
	if(pfont)
	{	
		delete pfont;
		pfont=NULL;
	}

	//
	// cameras
	delete m_pcamera;
	m_pcamera=NULL;
	delete m_pwaypointCam;
	m_pwaypointCam=NULL;

	//
	// frustum
	delete m_pfrustum;
	m_pfrustum=NULL;

	//ShowCursor(TRUE);
	RevealCursor();
	DeinitTextureManager();
	ShutdownLog();
}



/*
 *	handle keyboard messages
 */
void CSharksView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	switch(nChar)
	{
	case '1':
		SetCameraMode(WAYPOINT_CAMERA);
		break;
	case '2':
		SetCameraMode(FIRSTPERSON_CAMERA);
		break;
	case '3':
		SetCameraMode(SHARKEYE_CAMERA);
		break;
	case 'H':
	case 'h':
		m_bShowHelp = !m_bShowHelp;
		break;
	case VK_LEFT:
		roty -= YANGLE_SPEED;
		if(roty<-360)
			roty+=360;
		break;
	case VK_RIGHT:
		roty += YANGLE_SPEED;
		if(roty>360)
			roty-=360;
		break;
	case VK_PRIOR:	// page up key
		rotx += XANGLE_SPEED;
		if(rotx>360)
			rotx-=360;
		break;
	case VK_NEXT:	// page down key
		rotx -= XANGLE_SPEED;
		if(rotx<-360)
			rotx+=360;
		break;
	case VK_UP:
		if(m_cameraMode==WAYPOINT_CAMERA)
		{
			m_waypointCamZoom -= ZOOM_SPEED;
		}
		else
		{
			zoom -= ZOOM_SPEED;
		}
		break;

	case VK_DOWN:
		if(m_cameraMode==WAYPOINT_CAMERA)
		{
			m_waypointCamZoom += ZOOM_SPEED;
		}
		else
		{
			zoom += ZOOM_SPEED;
		}
		break;
	case VK_SPACE:
		m_bPaused = !m_bPaused;
		m_bWasPaused=m_bPaused;
		Invalidate(FALSE);
		break;


	
	/**** now I disable camera toggling with Ctr-C ****/
	//case 'C':
	//case 'c':
	//	if(GetKeyState(VK_SHIFT) & 0x800)	// if ALT key is pressed
	//		ToggleCameraMode();
	//	break;

	case VK_F1:
		ReadIniFile();
		break;

	case VK_F2:
		//spawnl(1,"SciTE/SciTE.exe",BuildEditorParameters().c_str(),0);
		break;
	}

	COpenGLView::OnKeyDown(nChar, nRepCnt, nFlags);
}


/*
 *	load the textures
 *	caustics etc.
 */
void CSharksView::LoadTextures()
{
	InitTextureManager(GL_REPEAT,TF_trilinear);

	//
	// load the water textures (caustics)
	char name[256];
	for (int i=0; i<32; i++)
	{
		sprintf(name,"Data/Water/water%02d.jpg",i);
		caustTexures[i] = LoadTexture(name);
	}

	//
	// load the ground texture
	//groundTexture = LoadTexture("Data/sub_sand2.jpg");
}


/*
 *	render the bottom of the sea
 */
void CSharksView::RenderGround()
{
	
	glPushAttrib(GL_CURRENT_BIT|GL_ENABLE_BIT);	// save current color
	if(GLEW_ARB_multitexture)
	{
		glActiveTextureARB(GL_TEXTURE0_ARB);	// if multitexturing, set active unit 
												// first, before binding texture...		
	}
	//glBindTexture(GL_TEXTURE_2D,groundTexture);
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	
	
	float step = float(m_terrainSize/m_terrainTile);
	glBegin(GL_QUADS);
	{
		glColor3f(.2f,.75f,.75f);
		glMateriali(GL_FRONT,GL_SHININESS,10);
        glNormal3f(0,1,0);

		for(int z=0; z<m_terrainTile; z++)
		{
			for (int x=0; x<m_terrainTile; x++)
			{
				glTexCoord2f(0,0);	
				glVertex3f(-m_terrainSize/2 + x*step, 
					m_planeHeight, m_terrainSize/2-z*step);
				glTexCoord2f(1,0);	
				glVertex3f(-m_terrainSize/2 + (x+1)*step, 
					m_planeHeight, m_terrainSize/2-z*step);
				glTexCoord2f(1,1);	
				glVertex3f(-m_terrainSize/2 + (x+1)*step, 
					m_planeHeight, m_terrainSize/2-(z+1)*step);
				glTexCoord2f(0,1);	
				glVertex3f(-m_terrainSize/2 + x*step, 
					m_planeHeight, m_terrainSize/2-(z+1)*step);
			}
		}		
	}
	glEnd();
	
	glPopAttrib();
	//glEnable(GL_LIGHTING);
}

/*
 *	right-clicking the mouse changes camera mode
 */
void CSharksView::OnRButtonDown(UINT nFlags, CPoint point)
{
	/***   Disable right-click camera toggle 
			too much frustration for the user   *****/		
	//ToggleCameraMode();
	COpenGLView::OnRButtonDown(nFlags, point);
}



/*
 *	Only update the title every 1/2 second
 *
 */
void CSharksView::CalcAndSetFPS(double dt)
{
	m_fps.fpsTime += dt;
	m_fps.m_frames++;

	if(m_fps.fpsTime < 0.5)
		return;

	char str[256];
	_snprintf(str,200,"%s [%d frames/sec]",
		(const char*)m_windowTitle,m_fps.m_frames*2);
	GetParentFrame()->SetWindowText(str);

	//
	// reset fps values for next update
	m_fps.fpsTime=0.0;
	m_fps.m_frames=0;
}

void CSharksView::ToggleCameraMode()
{
	if(m_cameraMode==FIRSTPERSON_CAMERA)
	{
		SetCameraMode(SHARKEYE_CAMERA);			
	}
	else if(m_cameraMode==SHARKEYE_CAMERA)
	{
		SetCameraMode(WAYPOINT_CAMERA);		
	}
	else
	{
		SetCameraMode(FIRSTPERSON_CAMERA);			
	}	
}



void CSharksView::ShowFishInfo( int fish_id )
{
	GLdouble wx,wy,wz; // screen coordinates
	GLfloat yoffset=0.1f;
	string message;

	Fish *pfish = m_pFishManager->GetFish(fish_id);

	if(pfish==NULL) return;

	Vector3 fishpos(pfish->GetPosition());
	fishpos.y += yoffset;	// set it a little higher

	GLdouble modelview[16];
	glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
	GLdouble projection[16];
	glGetDoublev(GL_PROJECTION_MATRIX,projection);
	GLint vieport[4];
	glGetIntegerv(GL_VIEWPORT,vieport);

	gluProject(fishpos.x,fishpos.y,fishpos.z,
		modelview,projection,vieport,
		&wx,&wy,&wz);

	gltext.Size(8);

	switch (pfish->GetCurrentAction())
	{
	case Fish::Cruise:
		message = "Cruising";
		break;
	case Fish::Chase:
		message = "Chasing";
		break;
	case Fish::Evade:
		message = "Evading";
		break;
	case Fish::Mate:
		message = "Mating";
		break;

	}

	gltext.Draw((int)wx,(int)wy, "%s",  message.c_str());
}
	
void CSharksView::ShowCameraHelp()
{
	CRect rect;
	GetWindowRect(&rect);
	int x = 20;
	int y = rect.Height()-30;

	switch(m_cameraMode) 
	{
	case FIRSTPERSON_CAMERA:
		gltext.Draw(x,y,"First Person Camera");
		gltext.Draw(x,y-20,"Look around using the mouse");
		gltext.Draw(x,y-40,"Move in horizontal space with the arrow keys");
		gltext.Draw(x,y-60,"Move up and down with PageUp and PageDown keys");
		break;
	case WAYPOINT_CAMERA:
		gltext.Draw(x,y,"Fish-to-shark Camera Mode");
		gltext.Draw(x,y-20,"Move from one shark to another using arrow buttons");
		gltext.Draw(x,y-40,"Zoom in and out with Up and Down arrow keys");
		break;
	case SHARKEYE_CAMERA:
		gltext.Draw(x,y,"Fish-eye Camera Mode");
		gltext.Draw(x,y-20,"You see what the shark sees...");
		break;	
	}
}

void CSharksView::ShowCredits()
{
	gltext.Draw(20,20,"Sharks demo by \\c(255 0 0)\\i+GM Kalatzantonakis\\i- "
		"\\c(255 255 255)2005-2006");	
}

void CSharksView::SetCameraMode(enumCameraMode mode)
{
	if(mode==WAYPOINT_CAMERA)
	{
		m_cameraMode=WAYPOINT_CAMERA;
		m_fovy=FOV_NORMAL;
		//ShowCursor(TRUE);
		RevealCursor();
		m_pwaypointCam->SetPosition(m_pcamera->GetPosition());
		m_pwaypointCam->SetView(m_pcamera->GetView());		
		m_bCameraFollowsFish=FALSE;
		m_waypointCamZoom=2.f;

		m_strCameraMode = "Waypoint Camera Mode \n(use arrows to follow next shark)";
	}
	else if(mode==FIRSTPERSON_CAMERA)
	{
		m_cameraMode=FIRSTPERSON_CAMERA;
		m_fovy=FOV_NORMAL;
		//ShowCursor(FALSE);
		HideCursor();

		//
		// set cursor position at the center of the screen
		CRect rect;
		CWnd *pwnd = GetParentFrame();
		pwnd->GetClientRect(&rect);
		int midx = rect.TopLeft().x + rect.Width()/2;
		int midy = rect.TopLeft().y + rect.Height()/2;
		SetCursorPos(midx,midy);

		m_pcamera->SetPosition(m_pwaypointCam->GetPosition());
		m_pcamera->SetView(m_pwaypointCam->GetView());
		m_bCameraFollowsFish=FALSE;

		m_strCameraMode = "First person Camera Mode \n(use "
			"arrow keys to move, mouse to look at, PageUp+PageDown to change height)";
	}
	else // SHARKEYE_CAMERA
	{
		m_cameraMode=SHARKEYE_CAMERA;
		m_fovy=FOV_SHARKEYE;
		//ShowCursor(TRUE);
		RevealCursor();
		if(m_iCameraFish<0 || m_iCameraFish>=m_pFishManager->GetSharkCount())
			m_iCameraFish=0;
		m_pCameraFish = m_pFishManager->GetFish(m_iCameraFish);
		m_bCameraFollowsFish=FALSE;

		m_strCameraMode = "Fish eye view. You see what the shark sees";
	}
	ResizeGLScene(m_width,m_height);	// apply the change to the fov
}


/*
 *	show the settings dialog
 *	pause the program while showing the dialog (if it wasn't paused)
 */
void CSharksView::OnSettingsProgramOptions()
{
	//
	// CSharkSettingsDlg's default constructor takes as argument a pointer
	// to the CSharksView that called it
	CSharkSettingsDlg dlg(this);

	//
	// save pause state so we can restore after the operation
	BOOL bWasPaused = m_bPaused;
	m_bPaused=TRUE;

	if (dlg.DoModal()==IDOK)
	{
		m_bShowCaustics = dlg.m_bShowCaustics;
		m_bShowPaths = dlg.m_bShowSharkPaths;
		m_bShowBoundingSpheres = dlg.m_bShowBoundingSpheres;
		m_bShowCredits = dlg.m_bShowCredits;
		m_bShowSharkShadows = dlg.m_bShowSharkShadows;
		m_bEnableCulling = dlg.m_bEnableCulling;
		m_bShowWireframe = dlg.m_bShowWireframe;
		m_bShowHelp = dlg.m_bShowHelp;
	}

	//
	// restore pause state
	m_bPaused=bWasPaused;
	
	Invalidate(FALSE);
}


/*
 *	view calls this after gaining the input focus.
 */
void CSharksView::OnSetFocus(CWnd* pOldWnd)
{
	COpenGLView::OnSetFocus(pOldWnd);

	m_bHasFocus=TRUE;
}



/*
 *	view calls this just before loose the input focus.
 */
void CSharksView::OnKillFocus(CWnd* pNewWnd)
{
	COpenGLView::OnKillFocus(pNewWnd);

	m_bHasFocus=FALSE;
}



/*
 *	
 */
void CSharksView::GoToNextShark()
{
	
	int nSharkCount = m_pFishManager->GetSharkCount();

	if(nSharkCount<1)	// no sharks
		return;
	
	//
	// if there is only one shark AND the camera shark pointer is already 
	// pointing to him, skip the rest
	if(nSharkCount==1 && m_iCameraFish==0 && m_pCameraFish!=NULL)
		return;

	if(++m_iCameraFish>=nSharkCount)
		m_iCameraFish=0;

	if(m_cameraMode!=WAYPOINT_CAMERA)
		SetCameraMode(WAYPOINT_CAMERA);

	m_pCameraFish = m_pFishManager->GetFish(m_iCameraFish);

	Vector3 pos = m_pCameraFish->GetPosition();
	//m_pwaypointCam->MoveTo(pos+Vector3(0,2,3),pos,3);
	m_pwaypointCam->MoveTo(pos+Vector3(0,m_waypointCamZoom,1.3f*m_waypointCamZoom),pos,3);
}

/*
 *	
 */
void CSharksView::GoToPrevShark()
{
	int nSharkCount = m_pFishManager->GetSharkCount();

	if(nSharkCount<1)	// no sharks
		return;

	//
	// if there is only one shark AND the camera shark pointer is already 
	// pointing to him, skip the rest
	if(nSharkCount==1 && m_iCameraFish==0 && m_pCameraFish!=NULL)
		return;

	if(--m_iCameraFish<0)
		m_iCameraFish=nSharkCount-1;

	if(m_cameraMode!=WAYPOINT_CAMERA)
		SetCameraMode(WAYPOINT_CAMERA);
	
	m_pCameraFish = m_pFishManager->GetFish(m_iCameraFish);

	Vector3 pos = m_pCameraFish->GetPosition();
	//m_pwaypointCam->MoveTo(pos+Vector3(0,2,3),pos,3);
	m_pwaypointCam->MoveTo(pos+Vector3(0,m_waypointCamZoom,1.3f*m_waypointCamZoom),pos,3);
}

void CSharksView::OnNavigationGotonextshark()
{
	m_bCameraFollowsFish=FALSE;
	GoToNextShark();
}



void CSharksView::OnNavigationGotopreviousshark()
{
	m_bCameraFollowsFish=FALSE;
	GoToPrevShark();
}

/*
 *	go to the center of the terrain (0,3,0), looking at (0,2,1) (just because)
 */
void CSharksView::OnNavigationGotocenterofterrain()
{
	if(m_cameraMode!=WAYPOINT_CAMERA)
		SetCameraMode(WAYPOINT_CAMERA);
	m_bCameraFollowsFish=FALSE;
	m_pwaypointCam->MoveTo(0,3,0,0,2,1,3.0);
}



/*
 *	
 */
void CSharksView::ReadIniFile()
{
	FILE* pf;
	char buff[256];
	char scriptname[256];
	
	pf = fopen("sharks.ini","r");
	
	if(pf==NULL)
		m_bIniFileExists=FALSE;
	else
		m_bIniFileExists=TRUE;


	if(!m_bIniFileExists)
	{
		m_pFishManager->Init();
		return;
	}
	

	
	while(!feof(pf))	
	{

		fgets(buff,255,pf);	// read line
		
		//
		// skip empty lines (with only newline characters)
		if( strlen(buff)<2)
			continue;
		// skip comments
		if( strncmp(buff,"//",2)==0)
			continue;
		
		if(sscanf(buff,"TERRAIN %f %d",&m_terrainSize,&m_terrainTile)==2)
			continue;
		if(sscanf(buff,"CAUSTICS %d",&m_bShowCaustics)==1)
			continue;
		if(sscanf(buff,"WIREFRAME %d",&m_bShowWireframe)==1)
			continue;
		if(sscanf(buff,"SHARKSHADOWS %d",&m_bShowSharkShadows)==1)
			continue;
		if(sscanf(buff,"SHARKPATHS %d",&m_bShowPaths)==1)
			continue;
		if(sscanf(buff,"BOUNDINGSPHERES %d",&m_bShowBoundingSpheres)==1)
			continue;
		/*else if(strcmp(buff,"WIREFRAME")==0)
			fscanf(pf,"%d",&m_bShowWireframe);*/
		if(sscanf(buff,"CULLING %d",&m_bEnableCulling)==1)
			continue;
		
		// caustic stuff
		if(sscanf(buff,"CAUSTICSCALE %f",&m_caustiScale)==1)
			continue;
		if(sscanf(buff,"CAUSTICINTERVAL %d",&m_changeCaustInterv)==1)
			continue;

		// lighting stuff
		if(sscanf(buff,"LIGHTAMBIENT %f %f %f %f",
			&m_matamb[0],&m_matamb[1],&m_matamb[2],&m_matamb[3])==4)
			continue;
		if(sscanf(buff,"LIGHTDIFFUSE %f %f %f %f",
			&m_matdiff[0],&m_matdiff[1],&m_matdiff[2],&m_matdiff[3])==4)
			continue;
		if(sscanf(buff,"LIGHTSPECULAR %f %f %f %f",
			&m_matspec[0],&m_matspec[1],&m_matspec[2],&m_matspec[3])==4)
			continue;
		if(sscanf(buff,"LIGHTPOSITION %f %f %f",
			&m_lightpos[0],&m_lightpos[1],&m_lightpos[2])==3)
			continue;
		

		if(sscanf(buff,"CLEARCOLOR %f %f %f %f",
			&m_clrColor[0],&m_clrColor[1],&m_clrColor[2],&m_clrColor[3])==4)
			continue;

		if(sscanf(buff,"DEFAULTSCENARIO %s",
			scriptname))
		{
			mStrMainScriptFile = scriptname;
			continue;
		}

		Vector3 vec;	
		if(sscanf(buff,"CAMERAPOSITION %f %f %f",
			&vec.x,&vec.y,&vec.z))
		{
			m_pcamera->SetPosition(vec);
			m_pwaypointCam->SetPosition(vec);
		}

		if (sscanf(buff,"CAMERAVIEW %f %f %f",
			&vec.x,&vec.y,&vec.z))
		{
			m_pcamera->SetView(vec);
			m_pwaypointCam->SetView(vec);
		}

		//
		// shark population
		//if(strncmp(buff,"SHARK",5)==0)
		//{
		//	fscanf(pf,"%s",modelname);	// read modelname
		//	
		//	//
		//	// if model is not already loaded, load it and store it to the
		//	// shark manager
		//	if(!m_pFishManager->IsModelLoaded(modelname))
		//	{
		//		FishModel *pmodel = new FishModel;
		//		pmodel->LoadFromAsciiMilkshape(modelname);
		//		m_pFishManager->mModels[modelname] = pmodel;
		//	}

		//	fscanf(pf,"%d", &numSegments);
		//	for (int i=0; i<numSegments; i++)
		//		fscanf(pf,"%f",&segments[i]);

		//	fscanf(pf,"%d",&rootindex);
		//	fscanf(pf,"%f %f %f",&pos.x,&pos.y,&pos.z);
		//	fscanf(pf,"%d",&rot);
		//	
		//	Fish* pshark = new Fish;
		//	pshark->Build(m_pFishManager->mModels[modelname],
		//		modelname,numSegments,rootindex,segments);
		//	pshark->ShowBones(false);
		//	pshark->SetPosition(pos);
		//	pshark->SetRotation(Quaternion().SetFromRadians(0,Deg2Rad(float(rot)),0));
		//	m_pFishManager->mFishes.push_back(pshark);			
		//}		
	}

	fclose(pf);
}

void CSharksView::OnNavigationFollowpreviousshark()
{
	GoToPrevShark();
	m_bCameraFollowsFish=TRUE;
	m_bWasPaused=m_bPaused;
	m_bPaused=TRUE;	// pause the game to allow camera to reach the shark
}

void CSharksView::OnNavigationFollownextshark()
{
	GoToNextShark();
	m_bCameraFollowsFish=TRUE;
	m_bWasPaused=m_bPaused;
	m_bPaused=TRUE; // pause the game to allow camera to reach the shark
}

void CSharksView::OnSize(UINT nType, int cx, int cy)
{
	CView::OnSize(nType, cx, cy);

	m_width=cx;
	m_height=cy;
	ResizeGLScene(cx,cy);
}



void CSharksView::ResizeGLScene(GLsizei cx,GLsizei cy)
{
	// Declare a variable to store the aspect ratio i.e the width to 
	// height ratio of the Window as the viewing frustum depends on this.
	GLdouble aspect_ratio; // width/height ratio

	// Return if the either the width or the height of the Window is 0
	if ( 0 >= cx || 0 >= cy )
	{
		// no need to do anything, since nothing is visible...
		return;
	}

	// The glViewport function sets the viewport. Compute the aspect ratio, 
	// select the projection matrix and clear it. Set the Viewing Volume. 
	// This means that all further commands will affect the projection matrix.
	// select the full client area
	glViewport(0, 0, cx, cy);

	// compute the aspect ratio
	// this will keep all dimension scales equal
	aspect_ratio = (GLdouble)cx/(GLdouble)cy;

	// select the projection matrix and clear it
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	// select the viewing volume
	// TODO give more control to the user of the class about the projection
	// so he doesn't need to override this method
	gluPerspective(m_fovy, aspect_ratio, 0.1f, 200.0f);

	// switch back to the modelview matrix and clear it
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}


void CSharksView::HideCursor()
{
	while(m_iCursorShow!=0)
	{
		ShowCursor(FALSE);
		m_iCursorShow--;
	}
}

void CSharksView::RevealCursor()
{
	ShowCursor(TRUE);
	m_iCursorShow++;
}




void CSharksView::LoadMainScript(const char* mainscript)
{
	
	//mStrMainScriptFile = ".\\scripts\\main.fish";
	LoadScript();
}


Fish* CSharksView::LoadFishFromString(vector<string> &inheritancePath, 
										string &fishName)
{
#ifdef KEEP_LOG
	static int sharkNo=1;
	
	string data("shark no ");
	data += sharkNo;
	for (vector<string>::iterator logiter=inheritancePath.begin();
		logiter!=inheritancePath.end(); logiter++)
	{
		data += " ";
		data += (*logiter);
		data += " ";
	}
	Log("%s\n",data.c_str());
	
#endif


	CParamHandler paramHandler;
	string modelfile = "";	
	int rootindex = 2;		
	//float *lengthsP;
	vector<float> lengths;
	Vector3 position;
	Vector3 rotation;
	int	numSegments;
	float segments[96];
	string strtype;
	Fish::Type fishtype;
	vector<float> speeds;
	vector<float> staminas;
	float nutrVal;
	float digestRate;
	vector<float> hunger;
	float seeRadius;
	float smellRadius;
	float hearRadius;
	float feedDistance;
	int	age;
	vector<float> lifeSpan;
	float agility;
	int alive;
	string gender;
	float reprodRate;
	float separation;
	float keepaway;

	//
	// put default values initially
	memset(segments,1,sizeof(float)*96);	// fill segments array with 1s

	

	vector<string>::reverse_iterator iter, iend;
	iter = inheritancePath.rbegin();
	iend = inheritancePath.rend();

	for (; iter!=iend; iter++)
	{
		paramHandler.Parse(*iter);

		if (paramHandler.HasValue("modelfile"))
		{
			modelfile = paramHandler.GetModelFile();
		}
		if (paramHandler.HasValue("rootindex"))
		{
			rootindex = paramHandler.GetRootIndex();
		}
		if (paramHandler.HasValue("position"))
		{
			position = paramHandler.GetPosition();
		}
		if (paramHandler.HasValue("rotation"))
		{
			rotation = paramHandler.GetRotation();
		}
		if (paramHandler.HasValue("segments"))
		{
			numSegments = paramHandler.GetSegments();
		}
		if (paramHandler.HasValue("lengths"))
		{
			lengths = paramHandler.GetLengths();
		}
		if (paramHandler.HasValue("type"))
		{
			strtype=paramHandler.GetType();
 		}
		if (paramHandler.HasValue("speed"))
		{
			speeds = paramHandler.GetSpeed();
		}
		else
		{
			speeds.push_back(1);
			speeds.push_back(2);
		}
		if (paramHandler.HasValue("stamina"))
		{
			staminas = paramHandler.GetStamina();
		}
		else
		{
			staminas.push_back(10);
			staminas.push_back(20);
		}
		if (paramHandler.HasValue("nutritional_value")) 
		{	
			nutrVal=paramHandler.GetNutritionalValue();
		}
		else
		{
			nutrVal=100;
		}
		if (paramHandler.HasValue("digestion_rate"))
		{
			digestRate=paramHandler.GetDigestionRate();
		}
		else
		{
			digestRate=1;
		}
		if (paramHandler.HasValue("hunger"))
		{
			hunger=paramHandler.GetHunger();
		}
		else
		{
			hunger.push_back(3);
			hunger.push_back(10);
		}
		if (paramHandler.HasValue("see_radius"))
		{
			seeRadius=paramHandler.GetSeeRadius();
		}
		else
		{
			seeRadius=5;
		}
		if (paramHandler.HasValue("hear_radius"))
		{
			hearRadius=paramHandler.GetHearRadius();
		}
		else
		{
			hearRadius=4;
		}
		if (paramHandler.HasValue("smell_radius"))
		{
			smellRadius=paramHandler.GetSmellRadius();
		}
		else
		{
			smellRadius=3;
		}
		if (paramHandler.HasValue("age"))
		{
			age=paramHandler.GetAge();
		}
		else
		{
			age=250;
		}
		if (paramHandler.HasValue("life_span"))
		{
			lifeSpan=paramHandler.GetLifeSpan();
		}
		else
		{
			lifeSpan.push_back(250);
			lifeSpan.push_back(500);
			lifeSpan.push_back(750);
		}
		if (paramHandler.HasValue("agility"))
		{
			agility=paramHandler.GetAgility();
		}
		else
		{
			agility=50;
		}
		if (paramHandler.HasValue("alive"))
		{
			alive=paramHandler.GetAlive();
		}
		else
		{
			alive=1;
		}
		if (paramHandler.HasValue("gender"))
		{
			gender=paramHandler.GetGender();
		}
		else
		{
			gender="male";
		}
		if (paramHandler.HasValue("feeding_distance"))
		{
			feedDistance=paramHandler.GetFeedingDistance();
		}
		else
		{
			feedDistance=0.5;
		}
		if (paramHandler.HasValue("reproduct_rate"))
		{
			reprodRate=paramHandler.GetReproductionRate();
		}
		else
		{
			reprodRate=0;
		}
		if (paramHandler.HasValue("prefered_separation"))
		{
			separation=paramHandler.GetSeparation();
		}
		else
		{
			separation=2;
		}
		if (paramHandler.HasValue("keepaway_distance"))
		{
			keepaway=paramHandler.GetKeepaway();
		}
		else
		{
			keepaway=5;
		}
	}

	if(0==strtype.compare(0,6,"salmon"))
		fishtype=Fish::Salmon;
	else if(0==strtype.compare(0,5,"shark"))
		fishtype=Fish::Shark;
	else
		fishtype=Fish::Dolphin;

	//
	// if model is not already loaded, load it and store it to the
	// shark manager
	if(!m_pFishManager->IsModelLoaded(modelfile.c_str()))
	{
		FishModel *pmodel = new FishModel;
		pmodel->LoadFromAsciiMilkshape(modelfile.c_str());
		m_pFishManager->mModels[modelfile.c_str()] = pmodel;
	}

	//lengthsP = new float[numSegments];
	if (lengths.size()<1)
	{
		// if no lengths vector defined, default is 1 for every segment
		//memset(lengthsP,1,numSegments);
		memset(segments,1,numSegments);
	}
	else
	{
		//memset(lengthsP,1,numSegments);
		memset(segments,1,numSegments);
		int maxloop = Max(numSegments, (int)lengths.size());
		for (int loop=0; loop<maxloop; loop++)
		{
			segments[loop] = lengths[loop];
		}
	}


	Fish* pfish = new Fish(m_pFishManager);
	pfish->Build(m_pFishManager->mModels[modelfile.c_str()],
		modelfile.c_str(),numSegments,rootindex,segments);
	pfish->SetType(fishtype);
	pfish->SetMinSpeed(speeds[0]);
	pfish->SetMaxSpeed(speeds[1]);
	pfish->SetMinStamina(staminas[0]);
	pfish->SetMaxStamina(staminas[1]);
	pfish->SetAgility(agility);
	pfish->SetAge(age);
	pfish->SetKeepawayDistance(keepaway);
	pfish->SetPreferredSeparation(separation);
	pfish->SetReproductRate(reprodRate);
	pfish->SetLifeSpan((int)lifeSpan[0], (int)lifeSpan[1], (int)lifeSpan[2]);
	pfish->SetSeeRadius(seeRadius);
	pfish->SetHearRadius(hearRadius);
	pfish->SetSmellRadius(smellRadius);
	pfish->SetIsAlive( (alive==1) );
	if( gender.compare(0,4,"male")==0 )
		pfish->SetGender( Fish::Male );
	else
		pfish->SetGender( Fish::Female);
	pfish->SetNutritionalValue(nutrVal);
	pfish->SetFeedingDistance(feedDistance);
	pfish->SetHungerRate(digestRate);
	pfish->SetMinHunger(hunger[0]);
	pfish->SetMaxHunger(hunger[1]);

	pfish->ShowBones(false);
	pfish->SetPosition(position);
	pfish->SetRotation(Quaternion().SetFromRadians(Deg2Rad(rotation[0]),
		Deg2Rad(rotation[1]),Deg2Rad(rotation[2])));
	

#ifdef KEEP_LOG
	
	
	sharkNo++;

#endif

	return pfish;
}


string CSharksView::BuildEditorParameters()
{

	char path[MAX_PATH] = {0};
	char buffer[256]={0};
	int lineNo=1;

	//FILE* f = fopen("./scripts/main.fish","r");
	FILE* f = fopen(mStrMainScriptFile.c_str(),"r");

	if (f)
	{
		//string line;
		//int no;


		//
		// here we search line-by-line the file for the "main" clause
		// the "main" clause is the entry-point of the scenario
		// lineNo keeps the number of the line where the "main" clause is so we pass
		// as an argument for the editor to go to this line from the beginning
		while ( fgets(buffer,256,f)!=NULL )
		{
			lineNo++;
			if (strstr(buffer,"main")!=0)
				break;	// ok, found it
		}

		fclose(f);
	}
	else
	{
		return "";
	}



	GetCurrentDirectory(MAX_PATH,path);

	string param("\"-cwd:");

	int i=0;
	int c = 1;


	// replace all '\\' characters with '/' characters
	while (true)
	{
		c = path[i];
		if(c==0)
			break;

		if( (char)c!='\\')
			param += (char)c;
		else
			param += "/";

		i++;
	}

	//
	// copy mStrMainScriptFile to tmpScriptName and then replace any '\\'
	// character with '/' (this is what SciTe editor wants)
	string tmpScriptName(mStrMainScriptFile);
	int len = (int)tmpScriptName.length();
	for (i=0; i<len; i++)
	{
		if(tmpScriptName[i]=='\\')
			tmpScriptName[i]='/';
	}

	
	param += "\" \"-open:";
	param += tmpScriptName;
	param += "\" -goto:";

	char val[10];
	param += itoa(lineNo,val,10);

	return param;
}
















void CSharksView::OnEditScripteditor()
{
	OpenEditorToEditScript();
}

void CSharksView::OnFileOpenscript()
{
	char cur_dir[MAX_PATH];
	GetCurrentDirectory(MAX_PATH, cur_dir);
	char filters[] = "fish script (*.fish)|*.fish|All files(*.*)|*.*|";
	CFileDialog dialog(TRUE,"fish","main.fish",NULL,filters,NULL);	
	CString filename;

	INT_PTR result = dialog.DoModal();

	SetCurrentDirectory(cur_dir);

	if(result==IDOK)
	{
		filename = dialog.GetPathName();
		mStrMainScriptFile = filename.GetString();
		//filename = dialog.GetFileName();
		//LoadModel(filename.c_str());		
		LoadScript();
	}	
}


BOOL CSharksView::LoadScript()
{
	if(mStrMainScriptFile.empty())
	{
#ifdef KEEP_LOG
		Log("CSharksView::LoadScript trying to open script with empty script name");
#endif
		return FALSE;
	}

#ifdef KEEP_LOG
	Log("Loading script %s",mStrMainScriptFile.c_str());
#endif

	//
	// clear all sharks and models before loading a new script
	m_pFishManager->Clear();

	string strfilename(""), strpath("");

	//
	// strip the path from the actual filename
	// find the last occurrence of character '\'
	basic_string<char>::size_type pos = mStrMainScriptFile.rfind("\\"); 
	
	if(pos==-1)
	{
		//	
		// no occurrence of '\' character
		strfilename = mStrMainScriptFile;
	}
	else
	{
		strpath = mStrMainScriptFile.substr(0,pos+1);
		strfilename = mStrMainScriptFile.substr(pos+1);
	}

	
	CPreprocessor prepr(strfilename,strpath);
	prepr.Process();

	vector<string>::iterator cBegin,cEnd;
	cBegin = prepr.ClassesBegin();
	cEnd = prepr.ClassesEnd();

	while (cBegin!=cEnd)
	{
		if (prepr.Exists(*cBegin))
		{

			vector<string> all = prepr.Get(*cBegin);
			Fish* pshark = LoadFishFromString(all,*cBegin);
			if(pshark)
				m_pFishManager->mFishes.push_back(pshark);
		}
		cBegin++;
	}

	m_pFishManager->CheckForInitialCollisions();

	return TRUE;
}



void CSharksView::OpenEditorForNewScript()
{
	spawnl(1,"SciTE/SciTE.exe"," ",0);
}

void CSharksView::OpenEditorToEditScript()
{
	spawnl(1,"SciTE/SciTE.exe",BuildEditorParameters().c_str(),0);
}
void CSharksView::OnEditorNewscript()
{
	OpenEditorForNewScript();
}

void CSharksView::OnEditReloadscript()
{
	LoadScript();
}


void CSharksView::TestRay()
{
	static double angle=0.0;
	m_box.SetCenter( (float)sin(angle)*4, 2, (float)cos(angle)*4);
	m_sphere.SetCenter((float)cos(angle),2+(float)sin(angle),0);

	pair<bool,float> result = m_ray.Intersects(m_box);

	if(result.first)
		DrawBoundingBox(m_box,1,0,0);	// draw it red
	else
		DrawBoundingBox(m_box);

	result = m_ray.Intersects(m_sphere);
	if (result.first)
	{	
		DrawSphere_colored(m_sphere,1,0,0);
	}
	else
	{
		DrawSphere_colored(m_sphere,1,0,1);
	}

	DrawRay(m_ray,100);

	angle+=0.008;
	if( angle>TWO_PI)
		angle-=TWO_PI;
}

